package com.zhrenjie04.alex.core.interceptor;

import java.util.ArrayList;
import java.util.UUID;

import javax.annotation.PostConstruct;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import com.zhrenjie04.alex.core.Permission;
import com.zhrenjie04.alex.core.User;
import com.zhrenjie04.alex.core.exception.CrisisError;
import com.zhrenjie04.alex.core.exception.UnauthorizedException;
import com.zhrenjie04.alex.util.SessionUtil;

/**
 * @author 张人杰
 */
public class AuthorizationInterceptor implements HandlerInterceptor {

	public static final String AUTHORIZATION_HEADER_KEY = "sid";

	@Value("${auth.open-swagger}")
	private Boolean openSwagger;
	@Value("${auth.system-code}")
	private String systemCode;
	@Value("${auth.unfiltered-codes}")
	private String unfilteredCodesString;
	private ArrayList<String> unfilteredCodes;

	@Value("${auth.default-authorized-codes}")
	private String defaultAuthorizedCodesString;
	private ArrayList<String> defaultAuthorizedCodes;

	@Value("${auth.unfilteredPathStartWith}")
	private String unfilteredPathStartWith;

	Logger logger = Logger.getLogger(AuthorizationInterceptor.class);

	@PostConstruct
	protected void init() {
		unfilteredCodes = new ArrayList<>();
		String[] codes = unfilteredCodesString.split("\\,");
		if (codes != null) {
			for (String code : codes) {
				unfilteredCodes.add(code);
			}
		}
		defaultAuthorizedCodes = new ArrayList<>();
		codes = defaultAuthorizedCodesString.split("\\,");
		if (codes != null) {
			for (String code : codes) {
				defaultAuthorizedCodes.add(code);
			}
		}
	}

	private String getPrivilegeCode(HandlerMethod method) {
		String code = "";
		Permission permission = method.getBean().getClass().getAnnotation(Permission.class);
		if (permission == null) {
			throw new CrisisError("BACKEND SYSTEM IS NOT ALLOWED TO CALL CLASS WITH NO PERMISSION ANNOTATION");
		}
		code += permission.value();
		permission = method.getMethod().getAnnotation(Permission.class);
		if (permission == null) {
			throw new CrisisError("BACKEND SYSTEM IS NOT ALLOWED TO CALL METHOD WITH NO PERMISSION ANNOTATION");
		}
		code += "." + permission.value();
		return code;
	}

	@Override
	public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
			throws Exception {
		// 从cookie获取sid
		String sid = null;
		Cookie[] cookies = request.getCookies();
		if (cookies != null) {
			for (Cookie cookie : cookies) {
				if (AUTHORIZATION_HEADER_KEY.equals(cookie.getName())) {
					sid = cookie.getValue();
					break;
				}
			}
		}
		// 从header获取sid
		if (sid == null) {
			sid = request.getHeader(AUTHORIZATION_HEADER_KEY);
		}
		// 非验证路径，生成sid
		if (request.getRequestURI().startsWith(unfilteredPathStartWith)) {
			if (sid == null) {
				sid = "t-" + UUID.randomUUID();
				request.setAttribute("sid", sid);
				Cookie cookie = new Cookie(AUTHORIZATION_HEADER_KEY, sid);
				cookie.setPath("/");
				cookie.setMaxAge(-1);
				response.addCookie(cookie);
			}
			return true;
		}
		if ("/error".equals(request.getRequestURI())) {
			return true;
		}
		if (openSwagger && (request.getRequestURI().startsWith("/swagger-resources")
				|| request.getRequestURI().startsWith("/v2/api-docs"))) {
			return true;
		}
		HandlerMethod method = (HandlerMethod) handler;
		String needCode = systemCode + ":" + getPrivilegeCode(method);
		// 不需要验证权限（不需要登录），则生成sid
		if (unfilteredCodes.contains(needCode)) {
			if (sid == null) {
				sid = "t-" + UUID.randomUUID();
				request.setAttribute("sid", sid);
				Cookie cookie = new Cookie(AUTHORIZATION_HEADER_KEY, sid);
				cookie.setPath("/");
				cookie.setMaxAge(-1);
				response.addCookie(cookie);
			}
			return true;
		}
		// 需要验证权限
		if (sid == null) {
			throw new UnauthorizedException("session已失效");
		}
		request.setAttribute("sid", sid);
		Cookie cookie = new Cookie(AUTHORIZATION_HEADER_KEY, sid);
		cookie.setPath("/");
		cookie.setMaxAge(-1);
		response.addCookie(cookie);
		User user = SessionUtil.getSessionUser(request);
		if (user == null) {
			throw new UnauthorizedException("session已失效");
		}
		// 所有访问都需要权限验证
		if (defaultAuthorizedCodes.contains(needCode) || user.getPrivilegeCodes().contains(needCode)) {
			return true;
		} else {
			throw new UnauthorizedException("没有对应的权限");
		}
	}

	@Override
	public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
			ModelAndView modelAndView) throws Exception {
	}

	@Override
	public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
			throws Exception {
	}

}
